#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    // Menu: File
    this->fileMenu = new QMenu("File", this);
    this->newFileAction = new QAction("New", this); this->newFileAction->setShortcut(tr("Ctrl+N"));
    this->openFileAction = new QAction("Open", this); this->openFileAction->setShortcut(tr("Ctrl+O"));
    this->saveFileAction = new QAction("Save", this); this->saveFileAction->setShortcut(tr("Ctrl+S"));
    this->exitAction = new QAction("Exit", this); this->exitAction->setShortcut(tr("Alt+F4"));

    this->fileMenu->addAction(this->newFileAction);
    this->fileMenu->addAction(this->openFileAction);
    this->fileMenu->addAction(this->saveFileAction);
    this->fileMenu->addSeparator();
    this->fileMenu->addAction(this->exitAction);

    // Menu: Edit
    this->editMenu = new QMenu("Edit", this);
    this->autoWrapAction = new QAction("Auto Wrap", this); this->autoWrapAction->setShortcut(tr("Ctrl+W"));
    this->autoWrapAction->setCheckable(true);
    this->autoWrapAction->setChecked(true);
    this->findAction = new QAction("Find/replace", this); this->findAction->setShortcut(tr("Ctrl+F"));
    this->readOnlyAction = new QAction("Read Only", this); this->readOnlyAction->setShortcut(tr("Ctrl+R"));
    this->readOnlyAction->setCheckable(true);
    this->readOnlyAction->setChecked(false);
    this->fontAction = new QAction("Font", this); this->fontAction->setShortcut(tr("Ctrl+Alt+F"));

    this->editMenu->addAction(this->autoWrapAction);
    this->editMenu->addAction(this->findAction);
    this->editMenu->addAction(this->readOnlyAction);
    this->editMenu->addAction(this->fontAction);

    // Menu: Style
    this->styleMenu = new QMenu("Style", this);
    this->defaultStyleAction = new QAction("Default", this); this->defaultStyleAction->setShortcut(tr("Ctrl+Alt+M"));
    this->darkStyleAction = new QAction("Dark", this); this->darkStyleAction->setShortcut(tr("Ctrl+Alt+N"));
    this->stickAction = new QAction("Top Window", this); this->stickAction->setShortcut(tr("Ctrl+T"));
    this->stickAction->setCheckable(true);
    this->stickAction->setChecked(false);
    this->styleMenu->addAction(this->defaultStyleAction);
    this->styleMenu->addAction(this->darkStyleAction);
    this->styleMenu->addAction(this->stickAction);

    // Menu: Help
    this->helpMenu = new QMenu("Help", this);
    this->aboutAction = new QAction("About MyEditor", this); this->aboutAction->setShortcut(tr("Ctrl+H"));
    this->helpMenu->addAction(this->aboutAction);

    // Final work
    this->mainMenuBar = this->menuBar();
    this->mainMenuBar->addMenu(this->fileMenu);
    this->mainMenuBar->addMenu(this->editMenu);
    this->mainMenuBar->addMenu(this->styleMenu);
    this->mainMenuBar->addMenu(this->helpMenu);

    this->quickRemoveTextSC = new QShortcut(tr("Ctrl+U"), this);
    this->quickRemoveTextSCS = new QShortcut(tr("Ctrl+ALT+U"), this);

    // =============================================================================
    // =============================================================================

    // TextArea
    this->textArea = new QPlainTextEdit();
    this->textArea->setFont(this->textFont);

    // Window
    QDesktopWidget* desktop = new QDesktopWidget();
    this->windowWidth = desktop->width() / 3;
    this->windowHeight = desktop->height() * 2 / 3;
    this->resize(this->windowWidth, this->windowHeight);
    this->setWindowIcon(QIcon(":/Images/Celestia.ico"));
    this->setWindowTitle(this->TITLE.c_str());
    this->setMenuBar(this->mainMenuBar);
    this->setCentralWidget(this->textArea);

    this->changeItemsFont();
    this->textArea->setFont(this->textFont);

    this->readConfigFile();

    connect(this->textArea, &QPlainTextEdit::textChanged, this, &MainWindow::modificationCheck);

    connect(this->newFileAction, &QAction::triggered, this, &MainWindow::newFile);
    connect(this->openFileAction, &QAction::triggered, this, &MainWindow::openFile);
    connect(this->saveFileAction, &QAction::triggered, this, &MainWindow::saveFile);
    connect(this->exitAction, &QAction::triggered, this, &MainWindow::exitApp);

    connect(this->autoWrapAction, &QAction::triggered, this, &MainWindow::changeWrapMode);
    connect(this->findAction, &QAction::triggered, this, &MainWindow::popTextFinder);
    connect(this->readOnlyAction, &QAction::triggered, this, &MainWindow::changeReadOnlyMode);
    connect(this->fontAction, &QAction::triggered, this, &MainWindow::popFontSetter);

    connect(this->defaultStyleAction, &QAction::triggered, this, &MainWindow::useDefaultStyle);
    connect(this->darkStyleAction, &QAction::triggered, this, &MainWindow::useDarkStyle);
    connect(this->stickAction, &QAction::triggered, this, &MainWindow::changeStickMode);

    connect(this->aboutAction, &QAction::triggered, this, &MainWindow::aboutME);
    connect(this->quickRemoveTextSC, &QShortcut::activated, this, &MainWindow::quickRemoveText);
    connect(this->quickRemoveTextSCS, &QShortcut::activated, this, &MainWindow::quickRemoveTextS);
}

void MainWindow::changeItemsFont() {
    this->mainMenuBar->setFont(this->DEFAULT_FONT);

    this->fileMenu->setFont(this->DEFAULT_FONT);
    this->newFileAction->setFont(this->DEFAULT_FONT);
    this->openFileAction->setFont(this->DEFAULT_FONT);
    this->exitAction->setFont(this->DEFAULT_FONT);

    this->editMenu->setFont(this->DEFAULT_FONT);
    this->autoWrapAction->setFont(this->DEFAULT_FONT);
    this->fontAction->setFont(this->DEFAULT_FONT);

    this->styleMenu->setFont(this->DEFAULT_FONT);
    this->defaultStyleAction->setFont(this->DEFAULT_FONT);
    this->darkStyleAction->setFont(this->DEFAULT_FONT);

    this->helpMenu->setFont(this->DEFAULT_FONT);
    this->aboutAction->setFont(this->DEFAULT_FONT);
}

void MainWindow::changeTextFont() {
    this->textFont = QFont(this->fontFamily.c_str(), this->fontSize, this->fontWeight, this->useItalic);
    this->textArea->setFont(this->textFont);
}

void MainWindow::read(const std::string filePath) {
    this->reader.open(filePath);
    if (!this->reader.good()) {
        QMessageBox::warning(
                    this,
                    "MyEditor - ERROR",
                    tr("Failed to read file \"%1\", please check!").arg(filePath.c_str()));
        this->reader.close();
        return;
    }
    this->filePath = filePath;
    this->setWindowTitle((this->TITLE + " - " + this->filePath).c_str());
    std::string fullContent = "";
    std::string line;
    while (getline(this->reader, line)) {
        if (fullContent.length() == 0)
            fullContent += line;
        else
            fullContent = fullContent + "\n" + line;
    }
    this->textArea->setPlainText(fullContent.c_str());
    this->reader.close();
    QFileInfo info(QFile(this->filePath.c_str()));
    if (info.isWritable()) {
        this->isReadOnlyFile = false;
    } else {
        this->isReadOnlyFile = true;
    }
    this->setEditMode();
    this->removeModifiedMark();
}

void MainWindow::write(const std::string& filePath) {
    this->writer.open(filePath);
    this->writer << this->textArea->toPlainText().toStdString();
    this->writer.close();
    QFileInfo info(QFile(filePath.c_str()));
    if (info.isFile() && info.isWritable())
        this->removeModifiedMark();
    else
        QMessageBox::warning(
                    this,
                    "MyEditor - ERROR",
                    tr("Failed to save file \"%1\", please check!").arg(filePath.c_str()));
}

// =============================================================================
// =============================================================================

// File
void MainWindow::newFile() {
    if (this->filePath.length())
        this->reader.open(this->filePath);
    if (this->isModified || (this->filePath.length() && !this->reader.good())) {
        if (this->reader.is_open())
            this->reader.close();
        QMessageBox::StandardButton choice = QMessageBox::question(
                    this,
                    tr("Before creating a new text file"),
                    "The file content has been modified. Do you want to save it first?",
                    QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
        if (choice == QMessageBox::Yes) {
            this->saveFile();
        } else if (choice == QMessageBox::Cancel) {
            return;
        }
    }
    if (this->reader.is_open())
        this->reader.close();
    this->filePath = "";
    this->textArea->clear();
    this->isReadOnlyFile = false;
    this->removeModifiedMark();
    this->setEditMode();
}

void MainWindow::openFile() {
    if (this->filePath.length())
        this->reader.open(this->filePath);
    if (this->isModified || (this->filePath.length() && !this->reader.good())) {
        if (this->reader.is_open())
            this->reader.close();
        QMessageBox::StandardButton choice = QMessageBox::question(
                    this,
                    tr("Before opening a new text file"),
                    "The file status has changed. Do you want to save it first?",
                    QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
        if (choice == QMessageBox::Yes) {
            this->saveFile();
            return;
        } else if (choice == QMessageBox::No) {
            QString filePath = QFileDialog::getOpenFileName(this, tr("Open File"), this->prevFSelPath.c_str(), tr("All files (*);;Text files (*.txt *.log *.sh *.bat *.conf *.ini *.list)"));
            if (filePath.length() == 0)
                return;
            this->read(filePath.toStdString());
            this->prevFSelPath = this->filePath.substr(0, this->filePath.rfind("/") + 1);
        } else {
            return;
        }
    } else {
        if (this->reader.is_open())
            this->reader.close();
        QString filePath = QFileDialog::getOpenFileName(this, tr("Open File"), this->prevFSelPath.c_str(), tr("All files (*);;Text files (*.txt *.log *.sh *.bat *.conf *.ini *.list)"));
        if (filePath.length() == 0)
            return;
        this->read(filePath.toStdString());
        this->prevFSelPath = this->filePath.substr(0, this->filePath.rfind("/") + 1);
    }
}

void MainWindow::saveFile() {
    if (this->filePath.length())
        this->reader.open(this->filePath);
    if (this->reader.good()) {
        if (!this->isModified) {
            if (this->reader.is_open())
                this->reader.close();
            return;
        }
    }
    if (this->filePath.length() == 0 || !this->reader.good()) {
        if (this->reader.is_open())
            this->reader.close();
        this->filePath = QFileDialog::getSaveFileName(this, tr("Save File"), this->prevFSelPath.c_str(), tr("All files (*)")).toStdString();
        if (this->filePath.length() == 0)
            return;
    }
    if (this->reader.is_open())
        this->reader.close();
    this->write(this->filePath);
    this->prevFSelPath = this->filePath.substr(0, this->filePath.rfind("/") + 1);
}

void MainWindow::exitApp() {
    if (this->filePath.length())
        this->reader.open(this->filePath);
    if (this->isModified || (this->filePath.length() && !this->reader.good())) {
        if (this->reader.is_open())
            this->reader.close();
        QMessageBox::StandardButton choice = QMessageBox::question(
                    this,
                    tr("Before exiting"),
                    "The file status has changed. Do you want to save it first?",
                    QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
        if (choice == QMessageBox::Yes) {
            this->saveFile();
        } else if (choice == QMessageBox::Cancel) {
            return;
        }
    }
    if (this->reader.is_open())
        this->reader.close();
    this->saveConfigFile();
    exit(0);
}

// =============================================================================
// =============================================================================

// Edit
void MainWindow::changeWrapMode() {
    this->autoWrapAction->isChecked() ?
        this->textArea->setLineWrapMode(QPlainTextEdit::WidgetWidth) :
        this->textArea->setLineWrapMode(QPlainTextEdit::NoWrap);
}

// =============================================================================
// =============================================================================

void MainWindow::aboutME() {
    QMessageBox::information(
                this, "About MyEditor",
                this->appInfo);
}

void MainWindow::recvFontOptsAndDelete() {
    this->changeTextFont();
    this->deleteFontSetter();
}

void MainWindow::recvFontOpts() {
    this->changeTextFont();
}

// =============================================================================
// =============================================================================

void MainWindow::popFontSetter() {
    this->fontSetter = new FontSetter(this);
    this->fontSetter->setAttribute(Qt::WA_ShowModal, true);
    this->fontSetter->resize(this->windowWidth, this->windowHeight / 2);
    this->fontSetter->getFontOpts(this->fontFamily, this->fontSize, this->fontWeight, this->useItalic);
    this->fontSetter->getDefaultFontOpts(this->DEFAULT_FONT_FAMILY, this->DEFAULT_FONT_SIZE, this->DEFAULT_FONT_WEIGHT, this->USE_ITALIC);
    connect(this->fontSetter, &FontSetter::sendFontOptsAndExit, this, &MainWindow::recvFontOptsAndDelete);
    connect(this->fontSetter, &FontSetter::sendFontOpts, this, &MainWindow::recvFontOpts);
    connect(this->fontSetter, &FontSetter::exitOnly, this, &MainWindow::deleteFontSetter);
    this->fontSetter->show();
}

void MainWindow::popTextFinder() {
    this->textFinder = new TextFinder(this);
    this->textFinder->setAttribute(Qt::WA_ShowModal, true);
    this->textFinder->getDefaultFontOpts(this->DEFAULT_FONT_FAMILY, this->DEFAULT_FONT_SIZE, this->DEFAULT_FONT_WEIGHT, this->USE_ITALIC);
    this->textFinder->setFixedSize(this->windowWidth, this->windowHeight / 2);
    connect(this->textFinder, &TextFinder::signalFindNext, this, &MainWindow::textFindNext);
    connect(this->textFinder, &TextFinder::signalFindPrev, this, &MainWindow::textFindPrev);
    connect(this->textFinder, &TextFinder::signalReplace, this, &MainWindow::textReplace);
    connect(this->textFinder, &TextFinder::signalReplaceAll, this, &MainWindow::textReplaceAll);
    this->textFinder->show();
}

void MainWindow::deleteFontSetter() {
    delete this->fontSetter;
}

void MainWindow::readConfigFile() {
    std::ifstream confReader(this->configPath);
    if (!confReader.good()) {
        confReader.close();
        return;
    }
    std::string line;
    while (getline(confReader, line)) {
        if (this->originalConfigStr.length() == 0)
            this->originalConfigStr = line;
        else {
            this->originalConfigStr += "\n";
            this->originalConfigStr += line;
        }

        if (line.find("FontFamily=") != std::string::npos) {
            this->fontFamily = line.substr(line.find("=") + 1);
        } else if (line.find("FontSize=") != std::string::npos) {
            this->fontSize = QString(line.substr(line.find("=") + 1).c_str()).toInt();
        } else if (line.find("FontWeight=") != std::string::npos) {
            this->fontWeight = FontSetter::str2FontWeight(line.substr(line.find("=") + 1));
        } else if (line.find("UseItalic=") != std::string::npos) {
            this->useItalic = (line.back() == '1');
        } else if (line.find("Style=") != std::string::npos) {
            this->currentStyleName = line.substr(line.find("=") + 1);
        } else if (line.find("PrevFSelPath=") != std::string::npos) {
            this->prevFSelPath = line.substr(line.find("=") + 1);
        } else if (line.find("ReadOnly=") != std::string::npos) {
            this->readOnlyMode = (line.back() == '1');
        } else if (line.find("Sticky=") != std::string::npos) {
            this->isSticky = (line.back() == '1');
        }
    }
    this->changeTextFont();
    this->setStyle();
    this->setEditMode();
    this->setStickMode();
    confReader.close();
}

void MainWindow::saveConfigFile() {
    if (!this->dir.exists(this->configDir.c_str())) {
        if (!this->dir.mkpath(this->configDir.c_str())) {
            QMessageBox::warning(this, "ERROR", tr("Failed to create configuration file storage directory '%1'!").arg(this->configDir.c_str()));
            return;
        }
    }
    std::ostringstream oss;
    oss << "[My Editor]\nFontFamily=" << this->fontFamily
        << "\nFontSize=" << this->fontSize
        << "\nFontWeight=" << FontSetter::fontWeight2Str(this->fontWeight)
        << "\nUseItalic=" << int(this->useItalic)
        << "\nStyle=" << this->currentStyleName
        << "\nPrevFSelPath=" << this->prevFSelPath
        << "\nReadOnly=" << int(this->readOnlyMode)
        << "\nSticky=" << int(this->isSticky);
    std::string configStr = oss.str();
    if (this->originalConfigStr == configStr)
        return;
    std::ofstream confWriter(this->configPath);
    confWriter << configStr;
    confWriter.close();
}

void MainWindow::closeEvent(QCloseEvent *event) {
    this->exitApp();
    event->ignore();
}

bool MainWindow::textFindNext(QString text, bool wholeWordMode, bool caseSensitive) {
    if (text.length() == 0) {
        QMessageBox::warning(this, "Find Next", "Empty Text!");
        return false;
    }

    QTextCursor originalCursor = this->textArea->textCursor();
    QTextCursor cursor = originalCursor;
    if (!cursor.hasSelection())
        cursor.movePosition(QTextCursor::StartOfBlock);
    this->textArea->setTextCursor(cursor);

    bool ret = false;
    if (wholeWordMode && caseSensitive) {
        ret = this->textArea->find(text, QTextDocument::FindWholeWords | QTextDocument::FindCaseSensitively);
    } else if (wholeWordMode) {
        ret = this->textArea->find(text, QTextDocument::FindWholeWords);
    } else if (caseSensitive) {
        ret = this->textArea->find(text, QTextDocument::FindCaseSensitively);
    } else {
        ret = this->textArea->find(text);
    }

    if (!ret) {
        QMessageBox::warning(this, "Find Next", tr("Cannot find next \"%1\"").arg(text));
        this->textArea->setTextCursor(originalCursor);
        return false;
    }
    return true;
}

bool MainWindow::textFindPrev(QString text, bool wholeWordMode, bool caseSensitive) {
    if (text.length() == 0) {
        QMessageBox::warning(this, "Find Previous", "Empty Text!");
        return false;
    }

    QTextCursor originalCursor = this->textArea->textCursor();
    QTextCursor cursor = originalCursor;
    if (!cursor.hasSelection())
        cursor.movePosition(QTextCursor::EndOfBlock);
    this->textArea->setTextCursor(cursor);

    bool ret = false;
    if (wholeWordMode && caseSensitive) {
        ret = this->textArea->find(text, QTextDocument::FindBackward | QTextDocument::FindWholeWords | QTextDocument::FindCaseSensitively);
    } else if (wholeWordMode) {
        ret = this->textArea->find(text, QTextDocument::FindBackward | QTextDocument::FindWholeWords);
    } else if (caseSensitive) {
        ret = this->textArea->find(text, QTextDocument::FindBackward | QTextDocument::FindCaseSensitively);
    } else {
        ret = this->textArea->find(text, QTextDocument::FindBackward);
    }

    if (!ret) {
        QMessageBox::warning(this, "Find Previous", tr("Cannot find previous \"%1\"").arg(text));
        this->textArea->setTextCursor(originalCursor);
        return false;
    }
    return true;
}

bool MainWindow::textReplace(QString text, QString replacer, bool wholeWordMode, bool caseSensitive, bool loopCallMode) {
    if (this->readOnlyMode || this->isReadOnlyFile) {
        QMessageBox::warning(
                    this,
                    "Replace",
                    "[ERROR] Attempting to modify a file in read-only mode!");
        return false;
    }

    if (text.length() == 0) {
        QMessageBox::warning(this, "Replace", "Empty Text!");
        return false;
    }

    QString selText = this->textArea->textCursor().selectedText();
    if(selText == text) {
        this->textArea->insertPlainText(replacer);
        return true;
    }

    QTextCursor originalCursor = this->textArea->textCursor();
    QTextCursor cursor = originalCursor;
    if (!cursor.hasSelection())
        cursor.movePosition(QTextCursor::StartOfBlock);
    this->textArea->setTextCursor(cursor);

    bool ret = false;
    if (wholeWordMode && caseSensitive) {
        ret = this->textArea->find(text, QTextDocument::FindWholeWords | QTextDocument::FindCaseSensitively);
    } else if (wholeWordMode) {
        ret = this->textArea->find(text, QTextDocument::FindWholeWords);
    } else if (caseSensitive) {
        ret = this->textArea->find(text, QTextDocument::FindCaseSensitively);
    } else {
        ret = this->textArea->find(text);
    }
    if (!ret) {
        if (!loopCallMode)
            QMessageBox::warning(this, "Replace", tr("Cannot find next \"%1\"").arg(text));
        this->textArea->setTextCursor(originalCursor);
        return false;
    }
    this->textArea->insertPlainText(replacer);
    return true;
}

void MainWindow::textReplaceAll(QString text, QString replacer, bool wholeWordMode, bool caseSensitive) {
    if (text.length() == 0) {
        QMessageBox::warning(this, "Replace", "Empty Text!");
        return;
    }

    QTextCursor cursor = this->textArea->textCursor();
    cursor.setPosition(0);
    this->textArea->setTextCursor(cursor);
    int cnt = 0;
    while (this->textReplace(text, replacer, wholeWordMode, caseSensitive, true)) {
        ++ cnt;
    }
    if (cnt > 1)
        QMessageBox::information(this, "Replace All", tr("The program replaced a total of %1 texts").arg(cnt));
    else
        QMessageBox::information(this, "Replace All", tr("The program replaced a total of %1 text").arg(cnt));
}

void MainWindow::modificationCheck() {
    if (this->isModified == false) {
        this->isModified = true;
        this->setModifiedMark();
    }
}

void MainWindow::setModifiedMark() {
    this->setWindowTitle(this->windowTitle() + " (*)");
}

void MainWindow::removeModifiedMark() {
    this->isModified = false;
    if (this->filePath == "")
        this->setWindowTitle(this->TITLE.c_str());
    else
        this->setWindowTitle((this->TITLE + " - " + this->filePath).c_str());
    this->setEditMode();
}

MainWindow::~MainWindow() {
    this->saveConfigFile();
}

void MainWindow::setStyle() {
    if (this->currentStyleName == "Dark") {
        this->useDarkStyle();
        return;
    }
    this->currentStyleName = "Default";
    this->useDefaultStyle();
}

void MainWindow::useDefaultStyle() {
    this->currentStyleName = "Default";
    qApp->setStyleSheet(this->DEFAULT_STYLESHEET);
}

void MainWindow::useDarkStyle() {
    this->currentStyleName = "Dark";
    qApp->setStyleSheet("FontSetter, TextFinder, QHeaderView, QMessageBox, QFileDialog"
                            "{background-color: #000000; color: white}"
                        "QMenu, QMenuBar {background-color: #151515; color: white}"
                        "QMenu::item:selected {background-color: #0099ff}"
                        "QLabel {color: white}"
                        "QPushButton, QLineEdit, QListWidget, QScrollBar, QTreeView, "
                        "QPlainTextEdit, QListView, QStatusBar, QComboBox, QComboBox::item "
                            "{background-color: #303030; color: white}");
}

void MainWindow::changeReadOnlyMode() {
    this->readOnlyMode = this->readOnlyAction->isChecked();
    this->setEditMode();
}

void MainWindow::setEditMode() {
    const char* readOnlyStr = " [ReadOnly]";
    this->readOnlyAction->setEnabled(this->isReadOnlyFile ? false : true);
    if (this->readOnlyMode || this->isReadOnlyFile) {
        this->textArea->setReadOnly(true);
        this->readOnlyAction->setChecked(true);
        if (this->isReadOnlyFile)
            this->readOnlyAction->setEnabled(false);
        else
            this->readOnlyAction->setEnabled(true);
        if (this->windowTitle().toStdString().find(readOnlyStr) == std::string::npos)
            this->setWindowTitle(this->windowTitle() + readOnlyStr);
    } else {
        if (this->windowTitle().toStdString().find(readOnlyStr) != std::string::npos) {
            std::string originalTitle = this->windowTitle().toStdString();
            std::string title = originalTitle.replace(originalTitle.find(readOnlyStr), strlen(readOnlyStr), "");
            this->setWindowTitle(title.c_str());
        }
        this->textArea->setReadOnly(false);
        this->readOnlyAction->setChecked(false);
        this->readOnlyAction->setEnabled(true);
    }
}

void MainWindow::quickRemoveText() {
    if (this->textArea->isReadOnly() || this->isReadOnlyFile)
        return;
    QTextCursor cursor = this->textArea->textCursor();
    if (cursor.atBlockStart()) {
        cursor.deletePreviousChar();
        return;
    }
    cursor.movePosition(QTextCursor::StartOfBlock);
    cursor.select(QTextCursor::BlockUnderCursor);
    cursor.setPosition(this->textArea->textCursor().position(), QTextCursor::KeepAnchor);
    cursor.deleteChar();
}

void MainWindow::quickRemoveTextS() {
    if (this->textArea->isReadOnly())
        return;
    QTextCursor cursor = this->textArea->textCursor();
    if (cursor.atBlockStart()) {
        cursor.deletePreviousChar();
        return;
    }
    cursor.movePosition(QTextCursor::StartOfLine);
    cursor.select(QTextCursor::LineUnderCursor);
    cursor.setPosition(this->textArea->textCursor().position(), QTextCursor::KeepAnchor);
    cursor.deleteChar();
}

void MainWindow::changeStickMode() {
    this->isSticky = this->stickAction->isChecked();
    if (this->isSticky)
        this->windowHandle()->setFlags(this->windowFlags() | Qt::WindowStaysOnTopHint);
    else
        this->windowHandle()->setFlags(Qt::Window);
}

void MainWindow::setStickMode() {
    if (this->isSticky) {
        this->setWindowFlags(Qt::WindowStaysOnTopHint);
        this->stickAction->setChecked(true);
    }
    else {
        this->stickAction->setChecked(false);
    }
}
